#ifndef ALARMENGINE_H
#define ALARMENGINE_H

#include <QObject>
#include <QMap>
#include <QTimer>
#include <QDateTime>
#include "../database/dbmanager.h"
#include "meter.h"

/**
 * @brief 报警类型枚举
 */
enum class AlarmType
{
    VoltageDropA,  ///< A相电压跌落
    VoltageDropB,  ///< B相电压跌落
    VoltageDropC,  ///< C相电压跌落
    OverVoltageA,  ///< A相过压
    OverVoltageB,  ///< B相过压
    OverVoltageC,  ///< C相过压
    UnderVoltageA, ///< A相欠压
    UnderVoltageB, ///< B相欠压
    UnderVoltageC, ///< C相欠压
    OverCurrentA,  ///< A相过流
    OverCurrentB,  ///< B相过流
    OverCurrentC,  ///< C相过流
    DeviceOffline  ///< 设备离线
};

/**
 * @brief 报警阈值配置结构
 */
struct AlarmThreshold
{
    double voltageDropThreshold;  ///< 电压跌落阈值（V），如：200V
    double overVoltageThreshold;  ///< 过压阈值（V），如：245V
    double underVoltageThreshold; ///< 欠压阈值（V），如：198V
    double overCurrentThreshold;  ///< 过流阈值（A），如：50A

    // 默认值（参考施耐德PM2220标准）
    AlarmThreshold()
        : voltageDropThreshold(200.0), overVoltageThreshold(245.0), underVoltageThreshold(198.0), overCurrentThreshold(50.0)
    {
    }
};

/**
 * @brief 报警事件结构
 */
struct AlarmEvent
{
    int alarmId;         ///< 报警ID（数据库自增ID）
    int meterId;         ///< 电表ID
    QString meterName;   ///< 电表名称
    AlarmType type;      ///< 报警类型
    QString typeName;    ///< 报警类型名称
    double value;        ///< 当前值
    double threshold;    ///< 阈值
    QDateTime timestamp; ///< 报警时间
    bool active;         ///< 是否激活（用于恢复检测）
    bool acknowledged;   ///< 是否已确认

    /**
     * @brief 生成报警描述
     */
    QString description() const
    {
        return QString("%1 %2 (当前值: %3, 阈值: %4)")
            .arg(meterName)
            .arg(typeName)
            .arg(value)
            .arg(threshold);
    }

    /**
     * @brief 生成唯一键（用于去重）
     * 格式：meterId_alarmType
     */
    QString uniqueKey() const
    {
        return QString("%1_%2").arg(meterId).arg(static_cast<int>(type));
    }
};

/**
 * @brief 报警引擎类
 *
 * 功能：
 * - 实时监控电表数据，检测报警条件
 * - 支持电压跌落、过压、欠压、过流等报警类型
 * - 报警去重机制（同一电表同一类型报警在恢复前只触发一次）
 * - 报警恢复检测（当参数回到正常范围时自动恢复）
 * - 报警记录自动入库
 * - 支持阈值配置
 */
class AlarmEngine : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int activeAlarmCount READ activeAlarmCount NOTIFY activeAlarmCountChanged)
    Q_PROPERTY(int totalAlarmCount READ totalAlarmCount NOTIFY totalAlarmCountChanged)
    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)

public:
    explicit AlarmEngine(DBManager *dbManager, QObject *parent = nullptr);
    ~AlarmEngine();

    /**
     * @brief 设置报警阈值
     * @param threshold 阈值配置
     */
    void setThreshold(const AlarmThreshold &threshold);

    /**
     * @brief 获取报警阈值
     */
    AlarmThreshold threshold() const { return m_threshold; }

    /**
     * @brief 启动报警引擎
     */
    void start();

    /**
     * @brief 停止报警引擎
     */
    void stop();

    /**
     * @brief 设置启用状态
     */
    void setEnabled(bool enabled);

    /**
     * @brief 获取启用状态
     */
    bool isEnabled() const { return m_enabled; }

    /**
     * @brief 添加监控电表
     * @param meter 电表对象
     */
    void addMeter(Meter *meter);

    /**
     * @brief 检查电表数据（手动触发）
     * @param meter 电表对象
     */
    void checkMeter(Meter *meter);

    /**
     * @brief 获取激活报警数量
     */
    int activeAlarmCount() const;

    /**
     * @brief 获取总报警数量
     */
    int totalAlarmCount() const { return m_totalAlarmCount; }

    /**
     * @brief 获取所有激活的报警事件
     */
    QVector<AlarmEvent> getActiveAlarms() const;

    /**
     * @brief 确认报警
     * @param alarmId 报警ID
     */
    bool acknowledgeAlarm(int alarmId);

    /**
     * @brief 获取报警类型名称
     */
    static QString getAlarmTypeName(AlarmType type);

signals:
    /**
     * @brief 报警触发信号
     * @param event 报警事件
     */
    void alarmTriggered(const AlarmEvent &event);

    /**
     * @brief 报警恢复信号
     * @param meterId 电表ID
     * @param type 报警类型
     */
    void alarmRecovered(int meterId, AlarmType type);

    /**
     * @brief 激活报警数量改变信号
     */
    void activeAlarmCountChanged();

    /**
     * @brief 总报警数量改变信号
     */
    void totalAlarmCountChanged();

    /**
     * @brief 启用状态改变信号
     */
    void enabledChanged();

private slots:
    /**
     * @brief 处理电表数据更新
     */
    void onMeterDataUpdated();

    /**
     * @brief 处理电表离线
     */
    void onMeterOffline();

    /**
     * @brief 定期检查报警恢复
     */
    void checkAlarmRecovery();

private:
    /**
     * @brief 检查电压报警
     */
    void checkVoltageAlarms(Meter *meter);

    /**
     * @brief 检查电流报警
     */
    void checkCurrentAlarms(Meter *meter);

    /**
     * @brief 触发报警
     * @param meter 电表对象
     * @param type 报警类型
     * @param value 当前值
     * @param threshold 阈值
     */
    void triggerAlarm(Meter *meter, AlarmType type, double value, double threshold);

    /**
     * @brief 恢复报警
     * @param uniqueKey 报警唯一键
     */
    void recoverAlarm(const QString &uniqueKey);

    /**
     * @brief 报警是否已激活
     * @param uniqueKey 报警唯一键
     */
    bool isAlarmActive(const QString &uniqueKey) const;

    /**
     * @brief 保存报警到数据库
     * @param event 报警事件
     * @return 报警ID
     */
    int saveAlarmToDatabase(const AlarmEvent &event);

    DBManager *m_dbManager;     ///< 数据库管理器
    AlarmThreshold m_threshold; ///< 报警阈值配置
    bool m_enabled;             ///< 是否启用

    QMap<int, Meter *> m_meters;              ///< 监控的电表（key: meterId）
    QMap<QString, AlarmEvent> m_activeAlarms; ///< 激活的报警（key: uniqueKey）

    QTimer *m_recoveryCheckTimer; ///< 恢复检查定时器
    int m_totalAlarmCount;        ///< 总报警次数
};

#endif // ALARMENGINE_H
